﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using SerialCommunication;
using System.Windows.Forms;
using MyClass;

namespace GPS_DB
{
    public class GPS_CMD
    {
        #region user vaviables
        private const byte MinimumLenOfFrame = 14;
        public byte ScrAdd;
        public byte DstAdd;
        public byte CmdType;
        public byte CMD;
        public string FrameStr;
        public string CmdStr;
        public string RecStr;

        public ArrayList CmdHistory = new ArrayList();
        #endregion

        public byte[] FrameByte = new byte[1024];
        private int FrameLength;
        public struct LINESTRUCT
        {
            public int mode;
            public string linename;
            public string disname;
        }
        public ArrayList LineArray = new ArrayList();

        public GPS_CMD()
        {
            FrameLength = 0;
        }

        public GPS_CMD(byte[] frame,int len)
        {
            CmdHistory.Clear();
            CleanVariables();
            for (int i = 0; i < len; i++)
            {
                FrameByte[i] = frame[i];
            }
            FrameLength = len;
            CMD_Analyze();
        }

        public void ReadIn(byte[] frame, int len)
        {
            CleanVariables();
            for (int i = 0; i < len; i++)
            {
                FrameByte[i] = frame[i];
            }
            FrameLength = len;
            CMD_Analyze();
        }

        public string DealWithLineData(byte[] tmpbyte, int index, int len)
        {
            int num = len / 30;
            string lineStr = "";
            LineArray.Clear();
            for (int i = 0; i < num; i++)
            {
                LINESTRUCT linedata1 = new LINESTRUCT();
                linedata1.mode = tmpbyte[index + i * 31];
                linedata1.linename = Encoding.Default.GetString(tmpbyte, index + i * 31 + 1, 8);
                linedata1.disname = Encoding.Default.GetString(tmpbyte, index + i * 31 + 9, 21);
                LineArray.Add(linedata1);

                lineStr += linedata1.mode.ToString() + " " + linedata1.linename + " " + linedata1.disname + "\r\n";
            }
            return lineStr;
        }

        private void CMD_Analyze()
        {
            if (FrameLength < 14)
                return;

            #region Command Information
            ScrAdd = FrameByte[4];
            DstAdd = FrameByte[6];
            CmdType = FrameByte[8];
            CMD = FrameByte[9];

            int k = 0;
            FrameStr = "";
            for (int i = 0; i < FrameLength; i++)
            {
                string s_temp = string.Format("{0:X}H", FrameByte[i]);
                if (s_temp.Length == 2)
                    s_temp = "0" + s_temp;
                FrameStr += s_temp + "  ";
                k++;
                if (k == 10)
                {
                    FrameStr += "\r\n";
                    k = 0;
                }
            }
            FrameStr += "\r\n";
            #endregion

            #region 02H-00H //公共位置信息
            if ((CmdType == 0x02) && (CMD == 0x00) && (FrameLength == 164) && (FrameByte[10] == 0x03) && (FrameByte[11] == 0x01))
            {
                CmdHistoryAdd(CMD);
                if (FrameByte[12] == 0x41)
                {
                    CmdStr = "";
                    RecStr = "";
                    char[] schar1 = new char[2];
                    schar1[0] = (char)0x20;
                    schar1[1] = '\0';
                    string tempstr;

                    #region 线路名称
                    tempstr = Encoding_GetString(FrameByte, 13, 8).Trim(schar1);
                    CmdStr += "---------------------------------------\r\n线路名称：" + tempstr.PadRight(6, '　');
                    RecStr = tempstr + " ";
                    #endregion

                    #region 区段名称
                    tempstr = Encoding_GetString(FrameByte, 23, 21).Trim(schar1);
                    CmdStr += "区段名称：" + tempstr + "\r\n";
                    RecStr += tempstr + " ";
                    #endregion

                    #region 线路代码
                    tempstr = (FrameByte[21] + FrameByte[22] * 256).ToString();
                    CmdStr += "线路代码：" + tempstr.PadRight(8, '　');
                    RecStr += tempstr + " ";
                    #endregion

                    #region 工作模式
                    tempstr = FrameByte[44].ToString();
                    CmdStr += "工作模式：" + tempstr + "\r\n";
                    RecStr += "模:" + tempstr + " ";
                    #endregion

                    #region 经纬度
                    if ((FrameByte[45] != 0xff) || (FrameByte[46] != 0xff))
                    {
                        tempstr = GF.BCDToHex(FrameByte[45], 2).ToString() + GF.BCDToHex(FrameByte[46], 2).ToString("00");
                        CmdStr += "经度：" + tempstr + "度";
                        RecStr += "经:" + tempstr + "度";
                        tempstr = GF.BCDToHex(FrameByte[47], 2).ToString("00") + "." + GF.BCDToHex(FrameByte[48], 2).ToString("00")
                            + GF.BCDToHex(FrameByte[49], 2).ToString("00");
                        CmdStr += tempstr + "分　";
                        RecStr += tempstr + "分 ";

                        tempstr = GF.BCDToHex(FrameByte[50], 2).ToString();
                        CmdStr += "纬度：" + tempstr + "度";
                        RecStr += "纬:" + tempstr + "度";
                        tempstr = GF.BCDToHex(FrameByte[51], 2).ToString("00") + "." + GF.BCDToHex(FrameByte[52], 2).ToString("00")
                            + GF.BCDToHex(FrameByte[53], 2).ToString("00");
                        CmdStr += tempstr + "分" + "\r\n";
                        RecStr += tempstr + "分 ";
                    }
                    #endregion

                    #region 调度电话
                    tempstr = Encoding_GetString(FrameByte, 60, 8).Trim();
                    CmdStr += "调度电话号码：" + tempstr.Trim(schar1);
                    RecStr += tempstr + " ";
                    #endregion

                    #region 时间
                    CmdStr +=   "    20" +
                                GF.BCDToHex(FrameByte[54], 2).ToString() + "-" +
                                GF.BCDToHex(FrameByte[55], 2).ToString() + "-" +
                                GF.BCDToHex(FrameByte[56], 2).ToString() + " " +
                                GF.BCDToHex(FrameByte[57], 2).ToString() + ":" +
                                GF.BCDToHex(FrameByte[58], 2).ToString() + ":" +
                                GF.BCDToHex(FrameByte[59], 2).ToString() + "\r\n---------------------------------------\r\n";
                    #endregion


                    #region 车站
                    for (int i = 0; i < 4; i++)
                    {
                        tempstr = Encoding_GetString(FrameByte, 68 + i * 18, 8);
                        CmdStr += "车站" + (i + 1).ToString() + ":" + tempstr.Trim(schar1).PadRight(5, '　');
                        RecStr += "站" + (i + 1).ToString() + ":" + tempstr.Trim(schar1).Trim() + " ";
                        
                        CmdStr += "代码:" + (FrameByte[76 + i * 18] + FrameByte[77 + i * 18] * 256).ToString().PadRight(7, ' ');

                        tempstr = Encoding_GetString(FrameByte, 78 + i * 18, 8);
                        CmdStr += "电话:" + tempstr.Trim(schar1) + "\r\n";
                        RecStr += "电话" + (i + 1).ToString() + ":" + tempstr.Trim(schar1)+" ";
                        
                    }
                    #endregion

                    #region errorFlag
                    string errorFlag = (FrameByte[140] + (short)FrameByte[141] * 16 * 16).ToString();
                    RecStr += (" :" + errorFlag);
                    #endregion
                }
                else
                {
                    CmdStr = "无效数据...";
                    RecStr = "无效数据...";
                }
            }
            #endregion

            #region 02H-A2H //回复
            else if ((CmdType == 0x02) && (CMD == 0xA2))
            {
                RecStr = FrameStr;
                RecStr += "回复\r\n";
            }
            #endregion

            #region 02H-01H //GPS通知MMI人工选择线路    进入选择区间
            else if ((CmdType == 0x02) && (CMD == 0x01))
            {
                RecStr = FrameStr;
                RecStr += "进入线路选择区域\r\n";
                RecStr += DealWithLineData(FrameByte, 10, FrameLength - 10);
            }
            #endregion

            #region 02H-12H //GPS通知MMI人工选择线路    回复查询附近线路
            else if ((CmdType == 0x02) && (CMD == 0x12))
            {
                RecStr = FrameStr;
                RecStr += "请确认线路：\r\n";
                RecStr += DealWithLineData(FrameByte, 10, FrameLength - 10);
            }
            #endregion

            #region 02H-03H //GPS通知MMI退出选择区域
            else if ((CmdType == 0x02) && (CMD == 0x03))
            {
                RecStr = FrameStr;
                RecStr += "退出线路选择区域";
            }
            #endregion

            #region 02H-0CH //GPS通知MMI进入强制选择状态
            else if ((CmdType == 0x02) && (CMD == 0x0C))
            {
                RecStr = FrameStr;
                RecStr += "GPS板进入强制状态";
            }
            #endregion

            #region 02H-0DH //GPS通知MMI退出强制选择状态
            else if ((CmdType == 0x02) && (CMD == 0x0D))
            {
                RecStr = FrameStr;
                RecStr += "GPS板退出强制状态";
            }
            #endregion

            #region 02H-A1H //进入模拟状态
            else if ((CmdType == 0x02) && (CMD == 0xa1))
            {
                RecStr = FrameStr;
                RecStr += "GPS板已进入模拟状态！";
                CmdStr = "GPS板已进入模拟状态！";
            }
            #endregion

            #region 02H-B2H //GPS板忙碌中
            else if ((CmdType == 0x02) && (CMD == 0xb2))
            {
                RecStr = FrameStr;
                RecStr += "GPS板忙碌中....";
                CmdStr = "GPS板忙碌中....";
            }
            #endregion

            #region 02H-A3H //退出模拟状态
            else if ((CmdType == 0x02) && (CMD == 0xa3))
            {
                RecStr = FrameStr;
                RecStr += "GPS板已退出模拟状态！";
                CmdStr = "GPS板已退出模拟状态！";
            }
            #endregion

            #region 03H-01H //已选择线路
            else if ((CmdType == 0x03) && (CMD == 0x01))
            {
                RecStr = FrameStr;
                RecStr += "已选择线路";
                CmdStr = "已选择线路";
            }
            #endregion

            #region 02H-A4H //查询版本
            else if ((CmdType == 0x02) && (CMD == 0xA4))
            {
                CmdHistoryAdd(CMD);
                switch (FrameByte[10])
                {
                    case 0:
                        break;
                    case 1:
                        string s1 = "数据库版本";
                        if (FrameLength == 14 + 20)
                        {
                            s1 += Encoding_GetString(FrameByte, 11, 19);//
                        }
                        else
                        {
                            s1 += Encoding_GetString(FrameByte, 11, 21);//远程升级数据库
                        }
                        RecStr = FrameStr;
                        RecStr += s1;
                        CmdStr = s1;
                        break;
                    case 2:
                        break;
                    case 3:
                        string s2 = "软件版本" + Encoding_GetString(FrameByte, 11, 19);
                        RecStr = FrameStr;
                        RecStr += s2;
                        CmdStr = s2;
                        break;
                }
            }
            #endregion

            #region 02H-30H //MMI电话薄命令
            else if (CMD == 0x30)
            {
                int len = ((int)FrameByte[2] << 8) + FrameByte[3] - 8;
                string s1 = "";

                if (len == 10)
                {
                    int error = ((int)FrameByte[19] << 8) + FrameByte[18];
                    s1 += "区段查询失败：" + string.Format("{0:X}H", error) + "\r\n";
                }
                else
                {
                    //int id = FrameByte[10] + ((int)FrameByte[11] << 8);
                    int totalframecount = FrameByte[10];
                    int currentframecount = FrameByte[11];
                    int totNum = FrameByte[12] + ((int)FrameByte[13] << 8);
                    int index = FrameByte[14] + ((int)FrameByte[15] << 8);
                    int num = FrameByte[16] + ((int)FrameByte[17] << 8);

                    s1 += "区段：[包序号:" + currentframecount.ToString() + "/" + totalframecount.ToString() + "] " +
                          "[区段号:" + index.ToString() + "/" + totNum.ToString() + "] " +
                          "[数量:" + num.ToString() + "]\r\n";

                    len -= 8;
                    for (int i = 0; i < len / 32; i++)
                    {

                        s1 += Encoding_GetString(FrameByte, 18 + 32 * i, 29) + FrameByte[18 + 32 * i + 29].ToString() + "\r\n";
                    }
                }
                RecStr = FrameStr;
                RecStr += s1;
                CmdStr = s1;
            }
            #endregion

            #region 02H-31H //MMI电话薄命令
            else if (CMD == 0x31)
            {
                
                int len = ((int)FrameByte[2] << 8) + FrameByte[3] - 8;

                string s1 = "";

                if (len == 10)
                {
                    int error = ((int)FrameByte[19] << 8) + FrameByte[18];
                    s1 += "线路查询失败：" + string.Format("{0:X}H", error) + "\r\n";
                }
                else
                {
                    int id = FrameByte[10] + ((int)FrameByte[11] << 8);
                    int totNum = FrameByte[12] + ((int)FrameByte[13] << 8);
                    int index = FrameByte[14] + ((int)FrameByte[15] << 8);
                    int num = FrameByte[16] + ((int)FrameByte[17] << 8);

                    s1 += "线路：[局:" + id.ToString() + "] " +
                          "[线路号:" + index.ToString() + "/" + totNum.ToString() + "] " +
                          "[数量:" + num.ToString();
                    len -= 8;
                    s1 += "] \r\n";
                    for (int i = 0; i < len / 16; i++)
                    {

                        s1 += Encoding_GetString(FrameByte, 18 + 16 * i, 16) + "\r\n";
                    }
                }

                RecStr = FrameStr;
                RecStr += s1;
                CmdStr = s1;
            }
            #endregion 

            #region 02H-32H //MMI电话薄命令
            else if (CMD == 0x32)
            {
                int len = ((int)FrameByte[2] << 8) + FrameByte[3] - 8;
                string s1 = "";

                if (len == 10)
                {
                    int error = ((int)FrameByte[19] << 8) + FrameByte[18];
                    s1 += "电话查询失败：" + string.Format("{0:X}H", error) + "\r\n";
                }
                else
                {
                    int id = FrameByte[10] + ((int)FrameByte[11] << 8);
                    int totNum = FrameByte[12] + ((int)FrameByte[13] << 8);
                    int index = FrameByte[14] + ((int)FrameByte[15] << 8);
                    int num = FrameByte[16] + ((int)FrameByte[17] << 8);

                    s1 += "电话：[局:" + id.ToString() + "] " +
                          "[包序号:" + num.ToString() + "/" + totNum.ToString() + "] " +
                          "[线路:" + index.ToString() + "]\r\n";
                    s1 += Encoding_GetString(FrameByte, 18, len - 8);
                }
                RecStr = FrameStr;
                RecStr += s1;
                CmdStr = s1;
            }
            #endregion

            #region 02H-33H //MMI读取错误
            else if (CMD == 0x33)
            {
                int len = ((int)FrameByte[2] << 8) + FrameByte[3] - 8;
                string s1 = "";

                if (len == 10)
                {
                    int error = ((int)FrameByte[19] << 8) + FrameByte[18];
                    s1 += "电话查询失败：" + string.Format("{0:X}H", error) + "\r\n";
                }
                else if (len == 2)
                {
                    int error = ((int)FrameByte[11] << 8) + FrameByte[10];
                    s1 += "电话查询失败：" + string.Format("{0:X}H", error) + "\r\n";
                }
                RecStr = FrameStr;
                RecStr += s1;
                CmdStr = s1;
            }
            #endregion

            #region 02H-36H //MMI读取所有分局信息
            else if (CMD == 0x36)
            {
                int len = ((int)FrameByte[2] << 8) + FrameByte[3] - 8;
                string s1 = "";

                if (len % 12 != 0)
                {
                    s1 += "读取所有分局信息错误" + "\r\n";
                }
                else
                {
                    int handlecnt = 10;
                    while (handlecnt < len + 10)
                    {
                        UInt32 numTem = FrameByte[handlecnt++];
                        numTem += ((UInt32)FrameByte[handlecnt++] << 8);
                        s1 += (numTem.ToString() + ".").PadRight(4);

                        numTem = FrameByte[handlecnt++];
                        s1 += " V." + numTem.ToString() + ".";
                        numTem = FrameByte[handlecnt++];
                        s1 += numTem.ToString();

                        UInt32 offset = FrameByte[handlecnt++];
                        offset += ((UInt32)FrameByte[handlecnt++] << 8);
                        offset += ((UInt32)FrameByte[handlecnt++] << 16);
                        offset += ((UInt32)FrameByte[handlecnt++] << 24);
                        s1 += "   :" + offset.ToString().PadRight(10);

                        UInt32 length = FrameByte[handlecnt++];
                        length += ((UInt32)FrameByte[handlecnt++] << 8);
                        length += ((UInt32)FrameByte[handlecnt++] << 16);
                        length += ((UInt32)FrameByte[handlecnt++] << 24);
                        s1 += " :" + length.ToString().PadRight(5);

                        s1 += "  (" + (offset + length).ToString() + ")\r\n";
                    }
                }
                RecStr = FrameStr;
                RecStr += s1;
                CmdStr = s1;
            }
            #endregion

            #region 02H-23H //入库查询新旧数据库版本
            else if ((CmdType == 0x02) && (CMD == 0x23))
            {
                string s1 = "旧数据库版本" + Encoding_GetString(FrameByte, 12, 21)+"\r\n";
                s1 += "新数据库版本" + Encoding_GetString(FrameByte, 33, 21) + "\r\n";
                RecStr = FrameStr;
                RecStr += s1;
                CmdStr = s1;
            }
            #endregion

            #region //未知命令
            else
            {
                RecStr = FrameStr;
                RecStr += "未知命令";
                CmdStr = "未知命令";
            }
            #endregion
        }

        private void CmdHistoryAdd(int cmd)
        {
            if (CmdHistory.Count > 100)
                CmdHistory.RemoveAt(0);
            CmdHistory.Add(CMD);
        }

        public string Encoding_GetString(byte[] tmpbyte, int index, int len)
        {
            string CMD_Str = "";
            try
            {
                CMD_Str = Encoding.Default.GetString(tmpbyte, index, len);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
            }
            return CMD_Str;
        }

        /// <summary>
        /// 以最小长度为标准进行判断
        /// </summary>
        /// <returns></returns>
        public bool IsValid()
        {
            if (FrameLength < MinimumLenOfFrame)
                return false;
            else
                return true;
        }

        /// <summary>
        /// 清除记忆
        /// </summary>
        private void CleanVariables()
        {
            FrameStr = "";
            CmdStr = "";
            RecStr = "";
            CMD = 0;
            CmdType = 0;
        }
        /////////////////////////////////////////////////////////////////////////////////
    }
}
